﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using FarseerPhysics.DebugViewXNA;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework.Input;
using SpriteGame.UI;
using SpriteGame.Helpers;
using SpriteGame.Entities;

namespace SpriteGame.Scenes
{
    enum EditorState
    {
        PLACE,
        MOVE,
        DELETE,
        CREATELINK,
        FINISHLINK
    }
    /// <summary>
    /// WINDOWS ONLY!
    /// </summary>
    class LevelEdit:Scene
    {
        const string SCENENAME = "ZombieScene";

        DebugViewXNA debugView;

        public LevelEdit(Game1 _parent)
            : base(_parent)
        {
            IsActive = true;
            currentState = EditorState.PLACE;
        }

        UIImageList images;
        bool spawnStatic = false;
        bool spawnBreakable = false;
        bool spawnRotated = false;
        bool spawnComplex = false;
        bool drawDebugData = true;

        EditorState currentState;
        BaseSprite selectedSprite = null;
        UIText cameraPos;

        public override void BuildHUD()
        {
            base.BuildHUD();

            int screenWidth = parent.GraphicsDevice.Viewport.Width;
            int screenHeight = parent.GraphicsDevice.Viewport.Height;
            int middle = screenWidth / 2;

            Hud.Clicked += new UIPanel.ClickHandler(Hud_Clicked);

            images = new UIImageList((parent.GraphicsDevice.Viewport.Width / 2) - 256, 0, 512, 168, "Textures/UI/SelectorMenu", TextureList.TEXTURES);
            Hud.AddChild(images);

            UIButton rightButton = new UIButton(middle + 246, 30, 30, 90, ">");
            rightButton.Clicked += new UIPanel.ClickHandler(rightButton_Clicked);
            UIButton leftButton = new UIButton(middle - 276, 30, 30, 90, "<");
            leftButton.Clicked += new UIPanel.ClickHandler(leftButton_Clicked);

            Hud.AddChild(rightButton);
            Hud.AddChild(leftButton);

            UIButton saveButton = new UIButton(10, 10, 256, 64, "Save Level");
            UIButton loadButton = new UIButton(10, 84, 256, 64, "Load Level");
            UIButton undoButton = new UIButton(10, 158, 256, 64, "Undo (ctrlz)");
            cameraPos = new UIText(10, 232, 256, 64, "{0,0}"); 
            UIButtonToggle staticButton = new UIButtonToggle(screenWidth - 266, 10, 256, 64, "StaticShape");
            UIButtonToggle physicsButton = new UIButtonToggle(screenWidth - 266, 84, 256, 64, "Pause Physics");
            UIButtonToggle breakableButton = new UIButtonToggle(screenWidth - 266, 158, 256, 64, "Breakable");
            UIButtonToggle rotatedButton = new UIButtonToggle(screenWidth - 266, 232, 256, 64, "Rotated");
            UIButtonToggle complexButton = new UIButtonToggle(screenWidth - 266, 306, 256, 64, "Complex");
            UIButtonToggle debugButton = new UIButtonToggle(screenWidth - 266, 380, 256, 64, "DebugView");
            Hud.AddChild(saveButton);
            Hud.AddChild(loadButton);
            Hud.AddChild(undoButton);
            Hud.AddChild(cameraPos);
            Hud.AddChild(staticButton);
            Hud.AddChild(physicsButton);
            Hud.AddChild(breakableButton);
            Hud.AddChild(rotatedButton);
            Hud.AddChild(complexButton);
            Hud.AddChild(debugButton);

            Hud.AddChild(new UIText(10, screenHeight - 40, 512,30, "Engine Editor - Click to place, hold right mouse button to navigate", true));

            saveButton.Clicked += new UIPanel.ClickHandler(saveButton_Clicked);
            loadButton.Clicked += new UIPanel.ClickHandler(loadButton_Clicked);
            undoButton.Clicked += new UIPanel.ClickHandler(undoButton_Clicked);
            staticButton.Clicked += new UIPanel.ClickHandler(staticButton_Clicked);
            physicsButton.Clicked += new UIPanel.ClickHandler(physicsButton_Clicked);
            breakableButton.Clicked += new UIPanel.ClickHandler(breakableButton_Clicked);
            rotatedButton.Clicked += new UIPanel.ClickHandler(rotatedButton_Clicked);
            complexButton.Clicked += new UIPanel.ClickHandler(complexButton_Clicked);
            debugButton.Clicked += new UIPanel.ClickHandler(debugButton_Clicked);
            //UIImage window = new UIImage(
            //Hud.AddChild(window);
            //window.AddChild(new UIImage(25, 45, 256, 128, "Textures/UI/BasicButton"));
            //window.AddChild(new UIButton(60, 350, 256, 128, "Hello World"));
        }

        void debugButton_Clicked(UIPanel _owner)
        {
            drawDebugData = !drawDebugData;
        }

        void complexButton_Clicked(UIPanel _owner)
        {
            UIButtonToggle button = (UIButtonToggle)_owner;
            spawnComplex = button.Value;
        }

        void rotatedButton_Clicked(UIPanel _owner)
        {
            UIButtonToggle button = (UIButtonToggle)_owner;
            spawnRotated = button.Value;
        }

        void breakableButton_Clicked(UIPanel _owner)
        {
            UIButtonToggle button = (UIButtonToggle)_owner;
            spawnBreakable = button.Value;
        }

        void physicsButton_Clicked(UIPanel _owner)
        {
            UIButtonToggle button = (UIButtonToggle)_owner;
            PausedPhysics = button.Value;
        }

        void leftButton_Clicked(UIPanel _owner)
        {
            images.PreviousImage();
        }

        void rightButton_Clicked(UIPanel _owner)
        {
            images.NextImage();
        }

        void staticButton_Clicked(UIPanel _owner)
        {
            UIButtonToggle button = (UIButtonToggle)_owner;
            spawnStatic = button.Value;
        }

        void Hud_Clicked(UIPanel _owner)
        {
            switch (currentState)
            {
                case (EditorState.PLACE):
                    if (spawnBreakable)
                    {
                        BodyType type = BodyType.Dynamic;
                        if (spawnStatic)
                        {
                            type = BodyType.Static;
                        }
                        float rotation = 0.0f;
                        if (spawnRotated)
                        {
                            rotation = (float)(Math.PI * 0.5);
                        }
                        BaseSprite block;
                            block = new DestructableBlock(this, type, InputHandler.GetMousePositionWorldCoords(), rotation, images.Image);
                        selectedSprite = block;
                        selectedSprite.Body.Awake = false;
                        AddEntity(block);
                        currentState = EditorState.MOVE;
                    }
                    else
                    {
                        BodyType type = BodyType.Dynamic;
                        if (spawnStatic)
                        {
                            type = BodyType.Static;
                        }
                        float rotation = 0.0f;
                        if (spawnRotated)
                        {
                            rotation = (float)(Math.PI * 0.5);
                        }
                        BaseSprite block;
                        if (spawnComplex)
                        {
                            block = new ComplexShape(this, type, InputHandler.GetMousePositionWorldCoords(), rotation, images.Image);
                        }
                        else
                        {
                            block = new BaseSprite(this, type, InputHandler.GetMousePositionWorldCoords(), rotation, images.Image);
                            //block = new AnimatedSprite(this, type, InputHandler.GetMousePositionWorldCoords(), rotation, images.Image);
                        }
                        selectedSprite = block;
                        selectedSprite.Body.Awake = false;
                        AddEntity(block);
                        currentState = EditorState.MOVE;
                    }
                    break;
                case (EditorState.MOVE):
                    if (InputHandler.LeftHold())
                    {

                    }

                    break;
                case (EditorState.DELETE):
                    break;
                case (EditorState.CREATELINK):
                    break;
                default:
                    break;
            }
        }

        void undoButton_Clicked(UIPanel _owner)
        {
            RemoveLastEntity();
        }

        void loadButton_Clicked(UIPanel _owner)
        {
            LoadScene(SCENENAME);
        }

        void saveButton_Clicked(UIPanel _owner)
        {
            SaveScene(SCENENAME);
        }

        public override void LoadContent()
        {
            base.LoadContent();
            debugView = new DebugViewXNA(World);
            DebugViewXNA.LoadContent(parent.GraphicsDevice, content);
            //Fixture ground = FixtureFactory.CreateEdge(world, new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f), 0);

            //AddEntity(new BaseSprite(this, BodyType.Static, new Vector2(0, 0), 0.0f, "Textures/Tiles_Long"));
            //AddEntity(new BaseSprite(this, BodyType.Static, new Vector2(51.2f, 12.8f), 0.0f, "Textures/Tiles_Long"));
            //for (int i = 0; i < 90; i++)
            //{
            //    AddEntity(new BaseSprite(world, 3.2f, 3.2f, BodyType.Dynamic, new Vector2(0, i* 250), "Textures/Tile"));
            //}
            //LoadScene("UIButtonScene");
        }

        public override void Update(GameTime _time)
        {
            switch (currentState)
            {
                case (EditorState.PLACE):
                    break;
                case (EditorState.MOVE):
                    if (InputHandler.LeftHold())
                    {
                        selectedSprite.Position = InputHandler.GetMousePositionWorldCoords();
                    }
                    else
                    {
                        selectedSprite.Body.Awake = true;
                        selectedSprite = null;
                        currentState = EditorState.PLACE;
                    }
                    break;
                case (EditorState.DELETE):
                    break;
                case (EditorState.CREATELINK):
                    break;
                default:
                    break;
            }

            if (InputHandler.RightHold())
            {
                Vector2 mouseChange = InputHandler.DeltaMouse;
                mouseChange.X *= -1;
                mouseChange *= 0.07f;
                parent.ViewCenterAdd(mouseChange);
                cameraPos.Text = parent.ViewCenter.ToString();
            }

            if (InputHandler.MiddleClick())
            {
                BaseSprite s = new GravityBall(this, 1.6f, 1.6f, BodyType.Dynamic, InputHandler.GetMousePositionWorldCoords(), 0.0f, "Textures/Debug/DebugBall");
                AddEntity(s);
                //BodyType bType = BodyType.Dynamic;
                //if (spawnStatic)
                //{
                //    bType = BodyType.Static;
                //}
                //ComplexShape p = new ComplexShape(this, bType, InputHandler.GetMousePositionWorldCoords(), 0.0f, images.Image);
                //AddEntity(p);
            }

            if (InputHandler.IsKeyPressed(Keys.W))
            {
                images.NextImage();
            }

            if (InputHandler.IsKeyPressed(Keys.Q))
            {
                images.PreviousImage();
            }

            if (InputHandler.IsKeyHeldDown(Keys.LeftControl) && InputHandler.IsKeyPressed(Keys.Z))
            {
                RemoveLastEntity();
            }
            base.Update(_time);
        }

        public override void Draw(Microsoft.Xna.Framework.GameTime _time)
        {
            base.Draw(_time);

            if (drawDebugData)
            {
                Matrix proje = parent.Projection;
                debugView.RenderDebugData(ref proje);
            }
        }
    }
}
